/*
 * Copyright (c) Honor Device Co., Ltd. 2021-2023. All rights reserved.
 */

package com.wangfugui.mybatisplus.common.utils;


import jodd.io.StreamGobbler;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageOutputStream;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;

/**
 * web工具类
 *
 * @author lwx0048678 liyu
 * @since 2021-11-12
 */
public class WebpUtils {
    private static final Logger log = LoggerFactory.getLogger(WebpUtils.class);

    /**
     * 转换成webp格式图片
     *
     * @param inputFile 待转换图片文件路径
     * @param outputFile 转换后的图片文件路径
     * @return boolean
     */
    public static boolean convertToWebp(String inputFile, String outputFile) {
        return convertToWebp(inputFile, outputFile, 100, null);
    }

    /**
     * 转换图片为WebP格式
     * @param original 原始图片流
     * @param quality 质量 (0.0-1.0)
     * @return WebP格式的字节数组
     */
    public static byte[] convertToWebp(InputStream original, float quality) throws IOException {
        BufferedImage image = ImageIO.read(original);

        try (ByteArrayOutputStream webpOut = new ByteArrayOutputStream()) {
            // 获取WebP图片写入器
            ImageWriter writer = ImageIO.getImageWritersByMIMEType("image/webp").next();

            ImageWriteParam writeParam = writer.getDefaultWriteParam();
            if (writeParam.canWriteCompressed()) {
                writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
                writeParam.setCompressionQuality(quality);
            }

            try (ImageOutputStream ios = ImageIO.createImageOutputStream(webpOut)) {
                writer.setOutput(ios);
                writer.write(null, new IIOImage(image, null, null), writeParam);
            }
            writer.dispose();

            return webpOut.toByteArray();
        }
    }

    /**
     * 转换成webp格式图片
     *
     * @param inputFile 待转换图片文件路径
     * @param outputFile 转换后的图片文件路径
     * @param quality 转换质量，0~100
     * @param utilPath 指定转换工具路径
     * @return boolean
     */
    public static boolean convertToWebp(String inputFile, String outputFile, Integer quality, String utilPath) {
        try {
            if (!new File(inputFile).exists()) {
                return false;
            }

            String outputPath = FilenameUtils.getFullPath(outputFile);
            if (!new File(outputPath).exists()) {
                boolean mkdirs = new File(outputPath).mkdirs();
                if (!mkdirs) {
                    log.error("failedTo Create File");
                }
            }

            return executeCWebp(inputFile, outputFile, quality, utilPath);
        } catch (Exception e) {
            log.error("exception When Executing Webp Conversion error: {}", e.getMessage());
            return false;
        }
    }

    /**
     * gifToWebp
     *
     * @param inputFile 请求参数
     * @param outputFile 请求参数
     * @param quality 请求参数
     * @param utilPath 请求参数
     * @return boolean
     */
    public static boolean gifToWebp(String inputFile, String outputFile, Integer quality, String utilPath) {
        try {
            if (!new File(inputFile).exists()) {
                return false;
            }

            String outputPath = FilenameUtils.getFullPath(outputFile);
            if (!new File(outputPath).exists()) {
                boolean mkdirs = new File(outputPath).mkdirs();
                if (!mkdirs) {
                    log.error("failedTo Create File");
                }
            }
            return execGifToWebp(inputFile, outputFile, quality, utilPath);
        } catch (Exception e) {
            log.error("exception When Executing Webp Conversion error: {}", e.getMessage());
            return false;
        }
    }

    /**
     * execute cwebp command：cwebp [options] input_file -o output_file.webp
     * 通过命令行转换成webp文件
     *
     * @param inputFile 待转换图片文件路径
     * @param outputFile 转换后的图片文件路径
     * @param quality 转换质量，0~100
     * @param utilPath 指定转换工具的路径
     * @return boolean
     */
    private static boolean executeCWebp(String inputFile, String outputFile, Integer quality, String utilPath) {
        try {
            // init cwebp path，and set privilege of 755.
            // you can replace cwebpath in your case. in this case, we used a macos-based cwebp
            String cwebpPath;
            if (StringUtils.isNotBlank(utilPath)) {
                cwebpPath = utilPath;
            } else if (OsInfoUtils.isWindows()) {
                cwebpPath = WebpUtils.class.getClass().getResource("/libwebp/cwebp_win64.exe").getPath();
            } else if (OsInfoUtils.isLinux()) {
                cwebpPath = WebpUtils.class.getClass().getResource("/libwebp/cwebp_linux").getPath();
            } else {
                log.error("current System IsNot Supported");
                return false;
            }

            StringBuilder command = new StringBuilder(cwebpPath);
            command.append(" -q " + (quality == 0 ? 80 : quality));
            command.append(" " + inputFile);
            command.append(" -o " + outputFile);
            Process proc = Runtime.getRuntime().exec(command.toString());
            StreamGobbler errorGobbler = new StreamGobbler(proc.getErrorStream(), System.err);
            StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream(), System.out);
            errorGobbler.start();
            outputGobbler.start();
            int exitVal = proc.waitFor();
            errorGobbler.join();
            outputGobbler.join();
            return exitVal == 0;
        } catch (Exception e) {
            log.error("webp conversion Failed, filePath {}, error: {}", inputFile, e.getMessage());
            return false;
        }
    }

    private static boolean execGifToWebp(String inputFile, String outputFile, Integer quality, String utilPath) {
        try {
            String webpPath;
            if (StringUtils.isNotBlank(utilPath)) {
                webpPath = utilPath;
            } else {
                log.error("currentSystem IsNot Supported");
                return false;
            }
            StringBuilder command = new StringBuilder(webpPath);
            command.append(" -q " + quality);
            command.append(" " + inputFile);
            command.append(" -o " + outputFile);
            Process proc = Runtime.getRuntime().exec(command.toString());
            StreamGobbler errorGobbler = new StreamGobbler(proc.getErrorStream(), System.err);
            StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream(), System.out);
            errorGobbler.start();
            outputGobbler.start();
            int exitVal = proc.waitFor();
            errorGobbler.join();
            outputGobbler.join();
            return exitVal == 0;
        } catch (Exception e) {
            log.error("webp conversion Failed, filePath {}, error: {}", inputFile, e.getMessage());
            return false;
        }
    }

}
